#! /usr/bin/env python

from dumper import Dumper
from dumper import LoadDumper
from dumper import RingDumper
from dumper import NetworkDumper
from scheduler import Scheduler
from utils import Accounter

import time
import os
import os.path
import logging
import atexit
import json
import signal

def clean_fifo():
    os.unlink('/var/run/xnopt/load.dat')
    os.unlink('/var/run/xnopt/net.dat')
    logging.debug('unlinked fifo: /var/run/xnopt/load.dat')

def sig_clean_fifo(signo, frame):
    os.unlink('/var/run/xnopt/load.dat')
    os.unlink('/var/run/xnopt/net.dat')
    logging.debug('unlinked fifo: /var/run/xnopt/load.dat')

def write_tables(*args):
    tables = {'domain_table':[], 'net_table':[]}
    domains = []
    logging.debug(str(args))
    for domid in args[0].keys():
        domain = {}
        domain['domain_id'] = domid
        domain['domain_load'] = args[0][domid][0]
        domain['ring_rx_of'] = args[0][domid][1]
        domain['pool_id'] = args[0][domid][2]
        domain['domain_type'] = (args[0][domid][3]<<1)|(args[0][domid][1])
        domains.append(domain)
        
    netstats = []
    for domid in args[1].keys():
        netstat = {}
        netstat['domain_id'] = domid
        netstat['bytes_rx'] = args[1][domid][0]
        netstat['bytes_tx'] = args[1][domid][1]
        netstat['packets_rx'] = args[1][domid][2]
        netstat['packets_tx'] = args[1][domid][3]
        netstats.append(netstat)
    tables['domain_table'] = domains
    tables['net_table'] = netstats
    args[2].write(str(tables))
    
# logging
logging.basicConfig(
        format = '[%(asctime)s] %(name)s:%(levelname)s: %(message)s'
)
logging.disable(logging.DEBUG)

# Init data path
factor = 1
load_dumper = LoadDumper('/var/run/xnopt/load.dat')
net_dumper = NetworkDumper('/var/run/xnopt/net.dat')
ring_dumper = RingDumper('/proc/ring/', factor)
ring_dumper.setDaemon(True)
ring_dumper.start()

tables_path = '/var/run/xnopt/tables.dat'
if os.path.exists(tables_path):
    os.unlink(tables_path)
os.mkfifo(tables_path)
tables_fifo = open(tables_path, 'w')

# Init number of physical CPU
num_pcpu = 6
dispatcher = Scheduler(num_pcpu)

# Init VM lists of pool-0 and pool-1 
#      CPU list of pool-0 and pool-1 
#pool_vm_lists = [{0:0,1:0,2:0,3:0,4:0,5:0,6:0}, {}]
#cpu_lists = [[0, 1, 2, 3, 4, 5], []]
pool_vm_lists = [{}, {}]
domids = os.listdir('/proc/ring')
for domid in domids:
    pool_vm_lists[0][int(domid)] = 0
cpu_lists = [[0, 1, 2, 3, 4, 5], []]
dispatcher.init_pools(pool_vm_lists, cpu_lists)

# Init an accounter
#accounter = Accounter()

atexit.register(clean_fifo)
signal.signal(signal.SIGTERM, sig_clean_fifo)
signal.signal(signal.SIGINT, sig_clean_fifo)

print "Network sensitive VMs optimization"

# Do scheduling
while True:
    time.sleep(0.1 * factor)
    load = load_dumper.dump()
    net_table = net_dumper.dump()
    ring = ring_dumper.dump()
    logging.debug("load, " + str(load))
    logging.debug("netstat" + str(net_table))
    logging.debug("ring" + str(ring))
    dispatcher.update(ring, load)
    dispatcher.dispatch()
    domain_table = dispatcher.get_domain_info()
    print "domain_table: " + str(domain_table)
    print "net_table: " + str(net_table)
    write_tables(domain_table, net_table, tables_fifo)
